package com.atguigu.gmall.common.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * @author 李旭
 * @date 2021/10/25 15:32
 * @Description:
 *
 *   自定义实现类
 */
@SuppressWarnings("all")
@Component
public class RabbitService {


    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    //发消息   要求：发送失败之后 可以在交换机应答 队列应答处 可以重新发消息
    //                             有交换机 RoutingKey Message 重发次数
    public void sendMessage(String exchange,String routingKey,Object msg){
        //子对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();

        //UUID 消息的唯一主键  32位
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);
        //CorrelationData 扩展几个成员变量
        //交换机
        gmallCorrelationData.setExchange(exchange);
        // RoutingKey
        gmallCorrelationData.setRoutingKey(routingKey);
        // Message
        gmallCorrelationData.setMessage(msg);
        // 重发次数

        //使用Redis保存gmallCorrelationData
        // K：uuid  V:gmallCorrelationData Jackson进行JSON转换  gmallCorrelationData必须实现序列化接口  JSON转换异常
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));
        //新问题 ：
        //  Jackson 转换 就需要序列化接口     Spring官方强烈推荐的产品   @RequestBody @ResponseBody
        //  JSONObject 转换 就不需要序列化接口吗？ 不需要   是阿里出品
        //  网上： 阿里的JSONObject 号称JSON转换 这一块是最快的

        //发消息  4个参数  correlationData ：发送失败之后 将此 correlationData 返回到交换机应答 队列应答处
         //可以重新发消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,gmallCorrelationData);

    }
    //发送基于死信的延迟消息
    public void sendDeadLetterMessage(String exchange,String routingKey,Object msg,int ttl){
        //关联系的数据对象   交换机应答失败 或队列应答失败  有个对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //UUID 消息的唯一主键  32位
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);
        //CorrelationData 扩展几个成员变量
        //交换机
        gmallCorrelationData.setExchange(exchange);
        // RoutingKey
        gmallCorrelationData.setRoutingKey(routingKey);
        // Message
        gmallCorrelationData.setMessage(msg);
        //是否为延迟消息
        gmallCorrelationData.setDelay(true);
        //延迟时长
        gmallCorrelationData.setDelayTime(ttl);

        //队列应答失败 准备的外力 缓存中数据
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));

        //延迟消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {
            //message.getMessageProperties().getHeaders().put("retryCount","3");
            //发消息设置TTL   初始化TTL队列 都设置TTL存活时间  最终以时间少的为准
            System.out.println("发消息的时间是：" + new Date());
            //设置TTL 的时间  ms
            message.getMessageProperties().setExpiration(String.valueOf(ttl*1000));// 发消息的TTL
            return message;
        },gmallCorrelationData);

    }
    //基于插件的延迟消息
    public void sendDelayedMessage(String exchange,String routingKey,Object msg,int delayTime){

        //关联系的数据对象   交换机应答失败 或队列应答失败  有个对象
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        //UUID 消息的唯一主键  32位
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        System.out.println("uuid:" + uuid);
        //CorrelationData 扩展几个成员变量
        //交换机
        gmallCorrelationData.setExchange(exchange);
        // RoutingKey
        gmallCorrelationData.setRoutingKey(routingKey);
        // Message
        gmallCorrelationData.setMessage(msg);
        //是否为延迟消息
        gmallCorrelationData.setDelay(true);
        //延迟时长
        gmallCorrelationData.setDelayTime(delayTime);
        //队列应答失败 准备的外力 缓存中数据
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));

        //延迟消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {
            //发消息设置TTL   初始化TTL队列 都设置TTL存活时间  最终以时间少的为准
            System.out.println("发消息的时间是：" + new Date());
            // 基于插件的延迟时间   ms
            message.getMessageProperties().setDelay(delayTime*1000);// 基于插件的延迟时间
            return message;
        },gmallCorrelationData);


    }

}
